/**
 * ┏┓　　　┏┓
 * ┏┛┻━━━┛┻┓
 * ┃　　　　　　　┃
 * ┃　　　━　　　┃
 * ┃　┳┛　┗┳　┃
 * ┃　　　　　　　┃
 * ┃　　　┻　　　┃
 * ┃　　　　　　　┃
 * ┗━┓　　　┏━┛
 * 　　┃　　　┃神兽保佑
 * 　　┃　　　┃代码无BUG！
 * 　　┃　　　┗━━━┓
 * 　　┃　　　　　　　┣┓
 * 　    ┃　　　　　　　┏┛
 * 　　┗┓┓┏━┳┓┏┛
 * 　　　┃┫┫　┃┫┫
 * 　　　┗┻┛　┗┻┛
 **/
package com.asd.common.listener.reflex;

import java.lang.reflect.Field;
import java.util.Map;

import com.asd.common.annotation.Autowired;
import com.asd.common.controller.BaseController;
import com.asd.common.utils.ClassUtil;
import com.jfinal.plugin.activerecord.Model;

/**
 * @author zhanqi
 * @Autowired自动注入实现
 * @date 2020-03-09
 */
public class AutowiredReflex {
    // 是否对超类进行注入
    private boolean autowiredSuperClass = true;

    /* Autowired自动注入实现 */
    public <T> T autowired(Class<?> targetClass, T targetObject) {
        try {
            doautowired(targetClass, targetObject);
            return targetObject;
        } catch (ReflectiveOperationException e) {
            throw new RuntimeException(e);
        }
    }

    protected void doautowired(Class<?> targetClass, Object targetObject) throws ReflectiveOperationException {
        Field[] fields = targetClass.getDeclaredFields();// 获取全部field
        if (fields.length != 0) {
            for (Field field : fields) {
                Autowired autowired = field.getAnnotation(Autowired.class);
                if (autowired == null) {
                    continue;
                }
                Class<?> fieldAutowiredClass = autowired.value();
                if (fieldAutowiredClass == Void.class) {
                    fieldAutowiredClass = field.getType();
                }
                Map<String, Class<?>> beanMap = BeanReflexMemory.of().getAllBean();
                ClassUtil classUtil = new ClassUtil();
                Class<?> fieldAutowired = classUtil.findFieldAutowiredClass(beanMap, fieldAutowiredClass);
                Object fieldAutowiredObject = fieldAutowired.newInstance();// 新建对象
                field.setAccessible(true);
                field.set(targetObject, fieldAutowiredObject);// 第一个参数存在注解的class对象，第二个参数field要设置的对象或者数据
            }
        }

        // 是否对超类进行注入
        if (autowiredSuperClass) {
            Class<?> c = targetClass.getSuperclass();
            if (c != BaseController.class && c != Object.class && c != Model.class && c != null) {
                doautowired(c, targetObject);
            }
        }
    }

}
